using MemoryPack;
using MessagePack;
using ProtoBuf;

namespace SerializeDemo;

public static class PlayPacketExtension
{
    public static byte[] ToByteArray(this FilePackage packet)
    {
        var type = packet.GetType();
        return MemoryPackSerializer.Serialize(type, packet);
    }
}

public enum CommandKey : byte
{
    None,
    Login,
    Register,
    Upload,
    Refresh,
}

[ProtoContract]
public abstract partial class BasePackage
{
    [Key(1)] [ProtoMember(1)] public CommandKey Key { get; set; }
}

public abstract class BaseAckPackage : BasePackage
{
    [ProtoMember(3)] public bool SuccessFul { get; set; }
}

public abstract partial class FilePackage
{
    private readonly Type _type;

    public FilePackage()
    {
        _type = this.GetType();
    }

    public CommandKey Key { get; set; }

    public virtual byte[] Encode()
    {
        return MemoryPackSerializer.Serialize(_type, this);
    }
}

[MemoryPackable]
public partial class Person
{
    public readonly int Age;
    public readonly string Name;

    // You can use a parameterized constructor - parameter names must match corresponding members name (case-insensitive)
    public Person(int age, string name)
    {
        this.Age = age;
        this.Name = name;
    }
}

[MemoryPackable]
public sealed partial class UploadPackage : FilePackage
{
    public string FileName { get; set; } = null!;

    public long FileLength { get; set; }

    public ReadOnlyMemory<byte> Body { get; set; }
}

[ProtoContract]
[MessagePackObject]
[MemoryPackable]
public sealed partial class LoginPackage : BasePackage
{
    [Key(2)] [ProtoMember(2)] public string? Username { get; set; }

    [Key(3)] [ProtoMember(3)] public string? Password { get; set; }
}

[ProtoContract]
public sealed class LoginAckPackage : BaseAckPackage
{
}